#
#  AppDelegate.rb
#  wov
#
#  Created by James Tuley on 4/2/08.
#  Copyright (c) 2008 __MyCompanyName__. All rights reserved.
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is WOV Suite.
#
# The Initial Developer of the Original Code is
# James Tuley.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#           James Tuley <jay+wov@tuley.name> (WOV Suite Author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */

require 'osx/cocoa'
require 'thread'
require 'fileutils' 

class AppDelegate < OSX::NSObject
	include OSX
	
	WOV_INPROGRESS_EXT = ".wov_InProgress"
	
	

	
	ib_action :openFiles
	def openFiles(aSender)
		tPanel = NSOpenPanel.openPanel
		tPanel.runModal
		application_openFiles(tPane.filenames)
		end
	
	def applicationWillFinishLaunching(aNotification)
		@fileQueue = []
		@count = 0
		@processStarted = false
		@mutex = Mutex.new
		@logMutex = Mutex.new
		@guid =NSProcessInfo.processInfo.globallyUniqueString
		
		@logController = LogController.alloc.init
		NSBundle.loadNibNamed_owner("Log",@logController)
		tLogLoc=NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,  NSUserDomainMask, true).at(0);
		tLogLoc=File.join(tLogLoc,"WOVConverter")
		FileUtils.mkdir_p(tLogLoc)
		tLogLoc=File.join(tLogLoc,"Log.rtfd")
		@logController.loadLogFromPath(tLogLoc)
		
		@multiChoiceController = ChoiceController.alloc.init
		NSBundle.loadNibNamed_owner("MultiChoice",@multiChoiceController)
		
		@wovChoiceController = ChoiceController.alloc.init
		NSBundle.loadNibNamed_owner("WOVChoice",@wovChoiceController)
		
		@progressController = ProgressController.alloc.init
		NSBundle.loadNibNamed_owner("Progress",@progressController)
		
				
		@combinedNameController = CombinedNameController.alloc.init
		NSBundle.loadNibNamed_owner("WOVCombinedName",@combinedNameController)
		
		NSDistributedNotificationCenter.defaultCenter.addObserver_selector_name_object_suspensionBehavior(@progressController, :updateDetail_, @guid, nil, NSNotificationSuspensionBehaviorDeliverImmediately)
		@processForLog=[]
		@progressTimer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats(1, @progressController, :refreshProgressWindow_,  nil, true)
		@logTimer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats(1, @logController, :refreshLogWindow_,  nil, true)
		
		end
	
	def applicationWillTerminate(aNotification)
		tLogLoc=NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,  NSUserDomainMask, true).at(0);
		tLogLoc=File.join(tLogLoc,"WOVConverter")
		FileUtils.mkdir_p(tLogLoc)
		tLogLoc=File.join(tLogLoc,"Log.rtfd")
				
		@logController.saveLogTo(tLogLoc)
		end
	
	def addMessageToLog(aMessage)
		@logMutex.synchronize{
			@processForLog.push(aMessage)
		}
		end
	
	def getMessagesForLog()
		tLogs =[]
		@logMutex.synchronize{
			tLogs =@processForLog
			@processForLog=[]
		}
		return tLogs
		end
	
	def isWovOrWovInProgress(aFile)
		return (aFile.lowercaseString.hasSuffix(".wov") || aFile.lowercaseString.hasSuffix(WOV_INPROGRESS_EXT.downcase))
	end
	
	ib_action :orderProgressFront
	def orderProgressFront(sender)
		@progressController.window.makeKeyAndOrderFront(sender)
		end
	
	ib_action :orderLogFront
	def orderLogFront(sender)
		@logController.window.makeKeyAndOrderFront(sender)
	end
	
	
	
	def progress
		if(@processStarted)
				return @count-1
			else
				return @count
		end
	end
	
	def progressTotal
		return (@fileQueue.length)
	end
	
	def getFileFromQueue
		tFile =nil
		@mutex.synchronize {
			tFile = @fileQueue.at(@count)
			@count = @count + 1
		}
		return tFile
	end
	
	def addFileToQueue(aFile)
		@mutex.synchronize do
			@fileQueue.push(GroupFiles.new(File.basename(aFile,File.extname(aFile)),[aFile]))
			end
		
		end
	
	def addFilesToQueue(aFiles,aCombinedName)
		@mutex.synchronize do
			@fileQueue.push(GroupFiles.new(aCombinedName,aFiles))
			end
		
		end
	
	def application_openFile(anApp, aFilename)
		application_openFiles(anApp, [aFileName])
	end
	
	def unwrapFiles(aFiles)
		aFiles.each{|item|
			tWOVMov = WOVMovie.wovWithPath(item)
			if(tWOVMov.isWOV)
				tWOVMov.restoreItems.each{|tNest| FileUtils.mv(tNest,tNest.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent) }
				end
			WOVUtil.safeTrash(item)
		}
	end
	
	def application_openFiles(anApp, aFilenames)
		
		tFilenames = aFilenames.sort
		
		wovNames = tFilenames.select{|aFilename| isWovOrWovInProgress(aFilename)}
		
		if (wovNames.length > 0)
			@wovChoiceController.fileList= wovNames
			@wovChoiceController.reload
			tAction =NSApp.runModalForWindow(@wovChoiceController.window)
			@wovChoiceController.window.orderOut(self)
			wovNames =@wovChoiceController.fileList
			case tAction
				when  1: wovNames.each{|aFile| self.addFileToQueue(aFile)}
				when  2: unwrapFiles(wovNames)
				when -1: return nil
				else puts "error"#todo
				end
			end
		
		
		otherNames = tFilenames.reject{|aFilename| isWovOrWovInProgress(aFilename) }
		
		
		if (otherNames.length > 1)
			@multiChoiceController.fileList= otherNames
			@multiChoiceController.reload
			tAction =NSApp.runModalForWindow(@multiChoiceController.window)
			otherNames =@multiChoiceController.fileList;
			@multiChoiceController.window.orderOut(self)
			
			
			case tAction
				when  1: otherNames.each{|aFile| self.addFileToQueue(aFile)}
				when  2: 
						@combinedNameController.produceNameForFiles(otherNames)
						tOut =NSApp.runModalForWindow(@combinedNameController.window)
						@combinedNameController.window.orderOut(self) 
						unless(tOut <= 0)
							self.addFilesToQueue(otherNames,@combinedNameController.choosenName)
						else
							return
						end
						
				when -1: return nil
				else puts "error"#todo
			end
			
			elsif (otherNames.length == 1)
			self.addFileToQueue(otherNames.first)
			end
		
		startProcessing
	end
	
	

	

	
		
	private
	
	def createM3UPlaylist(aWOVDir, aGroupFiles)
		tM3UPath =suggestNewPathWithExt(aWOVDir,aGroupFiles.name,"M3U")
		tFile = File.new(tM3UPath,"w+") 
		aGroupFiles.files.each{|anItem| tFile.write(File.basename(anItem)+"\r\n")}
		tFile.close
		return tM3UPath
	end
	
	def suggestNewPathWithExt(aWOVDir,aBasename,anExt)
		return WOVUtil.nonCollidingPath(File.join(aWOVDir,aBasename+"."+anExt))
	end
	
	def startProcessing
		unless @processStarted
			orderProgressFront(self)
			@processStarted=true
			@mutex.synchronize{
				tCount = @fileQueue.length - @count
				@fileQueue = @fileQueue.last(tCount)
				@count=0
			}
			Thread.new {
				while @count < @fileQueue.length
					tQueueFiles = getFileFromQueue
					tFilesToMove =[]
					tOrigFile = nil;
					if (isWovOrWovInProgress(tQueueFiles.files.first))
						tWOVProgPath =getWovInProgressPath(tQueueFiles)
						unless(tQueueFiles.files.first.isEqualToString(tWOVProgPath))
						FileUtils.mv(tQueueFiles.files.first,tWOVProgPath)
						end

						tWOVMov = WOVMovie.wovWithPath(tWOVProgPath)
						WOVMovie.writeNewWOVInfoPlist_toPath(tWOVMov,tWOVMov.infoPlistPath)

						tQuickLookDir = File.join(tWOVProgPath,"QuickLook")

						if(File.exist?(tQuickLookDir))

							FileUtils.remove_dir(tQuickLookDir)
						end 

					else
						tWOVProgPath = createInProgressDir(tQueueFiles)
						
						tNewFile = suggestNewPathWithExt(tWOVProgPath,tQueueFiles.name,"mov")
						unless tQueueFiles.files.length ==1
							tOrigFile = createM3UPlaylist(tWOVProgPath, tQueueFiles)
							tFilesToMove = tQueueFiles.files.inject([]){|aCombined,anItem| aCombined + getFilesToMove(anItem)}
						else
							tOrigFile = File.join(tWOVProgPath,File.basename(tQueueFiles.files.first))
							tFilesToMove = getFilesToMove( tQueueFiles.files.first)
						end
						

						WOVUtil.writeInfoPList(tWOVProgPath,File.basename(tOrigFile),
									   File.basename(tNewFile),tFilesToMove.collect{|anItem| File.basename(anItem)})
						

						tFilesToMove.each{|anItem| FileUtils.mv(anItem,tWOVProgPath) }
						

					end
					
					
					if Kernel.system(WOVUtil.helperPath,
									 tWOVProgPath,
									 @guid)
						tNewPath = finishedWithWov(tWOVProgPath)
						addMessageToLog("Success: "+tNewPath+"\n")
						
						else
						addMessageToLog("Failure: "+tWOVProgPath+"\n")
						
						end
					end					
				@processStarted=false
				
			}
		end
	end
	
	def getWovInProgressPath(aGroupFile)
		tFile =File.join(File.dirname(aGroupFile.files.first),aGroupFile.name+WOV_INPROGRESS_EXT)
		return tFile
	end
	
	def createInProgressDir(aGroupFile)
		tWOVProgPath =getWovInProgressPath(aGroupFile)
		FileUtils.mkdir(tWOVProgPath)
		return tWOVProgPath
	end
	
	def getFilesToMove(aFile)
		tFileWithoutExt = aFile.stringByDeletingPathExtension
		tSubFileExts = "{srt,ssa,sub,smi}"
		
		tFileArray =Dir.glob(tFileWithoutExt+".[a-z][a-z]."+tSubFileExts, File::FNM_CASEFOLD)
		
		tFileArray = tFileArray + Dir.glob(tFileWithoutExt+"."+tSubFileExts, File::FNM_CASEFOLD)
		
		tFileArray = tFileArray + [aFile]
		return tFileArray
	end
	
	def finishedWithWov(aWOVProg)
		tNewPath = WOVUtil.rubyPathByDeletingExtension(aWOVProg)+".wov"
		FileUtils.mv(aWOVProg,WOVUtil.nonCollidingPath(tNewPath))
		return tNewPath
	end
	
end
